package com.ndp.fb.walle.business.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ndp.ec.core.model.EcCustomer;
import com.ndp.fb.enums.KeysConstant;
import com.ndp.fb.enums.PlatForm;
import com.ndp.fb.exception.ga.NoGaProfileIdException;
import com.ndp.fb.exception.ga.NoTokenException;
import com.ndp.fb.model.rdb.AudienceManager;
import com.ndp.fb.model.report.param.EcReportInputParam;
import com.ndp.fb.mongo.api.EcReportMongoService;
import com.ndp.fb.mongo.api.ProductSetMongoService;
import com.ndp.fb.rdb.api.AudienceManagerRdbService;
import com.ndp.fb.rdb.api.EcTemplateMaterielRdbService;
import com.ndp.fb.rdb.api.ProductConfigurationRdbService;
import com.ndp.fb.rdb.api.ProductManageRdbService;
import com.ndp.fb.rdb.model.EcTemplateMateriel;
import com.ndp.fb.rdb.model.EntrustAccount;
import com.ndp.fb.rdb.model.adpublishcondition.UserConnectionPage;
import com.ndp.fb.rdb.model.productmanage.ProductManage;
import com.ndp.fb.rdb.model.productmanage.ProductManageExt;
import com.ndp.fb.walle.business.EcService;
import com.ndp.fb.walle.business.FetchGoogleGaDataService;
import com.ndp.fb.walle.model.vo.SimpleVo;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * Created by infi.he on 2016/3/17.
 */
@Component
public class EcServiceImpl implements EcService {
    private static Logger logger = LoggerFactory.getLogger(EcServiceImpl.class);

    @Autowired
    private FetchGoogleGaDataService fetchGoogleGaDataService;

    @Reference
    private ProductManageRdbService productManageRdbService;

    @Reference
    private EcReportMongoService ecReportMongoService;

    @Autowired
    private AdPublishConditionServiceImpl adPublishConditionService;
    @Reference
    private ProductConfigurationRdbService productConfigurationRdbService;
    @Reference
    private AudienceManagerRdbService audienceManagerRdbService;
    @Reference
    private ProductSetMongoService productSetMongoService;
    @Reference
    private EcTemplateMaterielRdbService ecTemplateMaterielRdbService;

    @Override
    public Map<String, Object> report(Long orgId, String userTicket, EcReportInputParam ecReportInputParam) {
        logger.info("report service start>>>");
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> convertedList = new ArrayList();
        Map<String, Object> fbDataFromMongo = ecReportMongoService.findFbDataFromMongo(userTicket, ecReportInputParam);
        if (!CollectionUtils.isEmpty(fbDataFromMongo)) {
            Set<String> adNames = new HashSet<>();
            List<Map<String, Object>> fbDataList = (List<Map<String, Object>>) fbDataFromMongo.get("data");
            fbDataList.forEach(fbData -> {
                // 转换后的结果
                Map<String, Object> convertedData = new HashMap<>();
                Map gaInputParam = new HashMap();
                // 下面这些属性会提取到外层，并且也是调用GA时需要的参数，因此直接从对象中删除掉，返回值传给GA
                for (String field : KeysConstant.ALL_GROUP_FIELDS) {
                    Object value = fbData.remove(field);
                    if (null != value) {
                        gaInputParam.put(field, value);
                        convertedData.put(field, value);
                        if ("adNames".equals(field)) {
                            adNames.addAll((List<String>) value);
                        }
                    }
                }
                convertedData.put("fbData", fbData);
                convertedList.add(convertedData);
            });
            List listWithGaData = null;
            try {
                Object allAdNamesStr = fbDataFromMongo.get("allAdNames");
                Object allAdIdsStr = fbDataFromMongo.get("allAdIds");
                Set<String> allAdNames = convertNestListToList(allAdNamesStr);
                Set<String> allAdIds = convertNestListToList(allAdIdsStr);

                Map gaInputParam = new HashMap<>();
                gaInputParam.put("productManageProductId", NumberUtils.createLong(ecReportInputParam.getFilters().getWebSite().get(0)));
                gaInputParam.put("orgId", orgId);
                gaInputParam.put("list", convertedList);
                gaInputParam.put("adNames", adNames);
                gaInputParam.put("allAdNames", allAdNames);
                gaInputParam.put("allAdIds", allAdIds);
                gaInputParam.put("groups", ecReportInputParam.getGroups());
                gaInputParam.put("filters", ecReportInputParam.getFilters());
                Integer allSpend = null == fbDataFromMongo.get("allSpend") ? 0 : (Integer) fbDataFromMongo.get("allSpend");
                gaInputParam.put("allSpend", allSpend);
                listWithGaData = fetchGoogleGaDataService.queryGaData(gaInputParam);
            } catch (NoTokenException | NoGaProfileIdException e) {
                logger.error("xx", e);
            } catch (Exception e) {
                logger.error("查询GA数据出错", e);
            } finally {
                if (CollectionUtils.isEmpty(listWithGaData)) {
                    result.put("list", convertedList);
                } else {
                    result.put("list", listWithGaData);
                    if (listWithGaData != null) {
                        Map<String, Object> gaSummaryMap = (Map<String, Object>) listWithGaData.remove(listWithGaData.size() - 1);
                        if (gaSummaryMap != null) {
                            Map<String, Object> gaSummary = (Map<String, Object>) gaSummaryMap.get("gaSummary");
                            result.put("gaSummary", gaSummary);
                        }
                    }
                }
                result.put("fbSummary", fbDataFromMongo.get("summary"));
            }
        } else {
            logger.info("ecReport query mongo empty!");
        }
        logger.info("report service end>>>");
        return result;
    }

    /**
     * 将嵌套List转为List
     *
     * @param nestListStr 原始嵌套List的JSON串
     * @return 转换后的List
     */
    private Set convertNestListToList(Object nestListStr) {
        Set resultList = new HashSet<>();
        if (null != nestListStr) {
            List<List> nestListArray = JSON.parseArray(nestListStr.toString(), List.class);
            if (null != nestListArray) {
                nestListArray.forEach(nestList -> {
                    if (null != nestList) {
                        resultList.addAll(nestList);
                    }
                });
            }
        }
        return resultList;
    }

    @Override
    public Collection<EcCustomer> getAllEcCustomerWithFbAccount(String userId) {
        List<ProductManageExt> ecCustomersWithFbAccountByOrgId = productManageRdbService.findEcCustomersWithFbAccountByUserId(userId);
        // 根据产品id进行分组
        Map<Long, List<ProductManageExt>> collect = ecCustomersWithFbAccountByOrgId.stream().collect(Collectors.groupingBy(ProductManageExt::getProdId));
        Collection<EcCustomer> result = new ArrayList<>();
        // 处理分组结果，将其转换为WebSiteFbAccount
        for (Map.Entry<Long, List<ProductManageExt>> entry : collect.entrySet()) {
            EcCustomer ecCustomer = new EcCustomer();
            ecCustomer.setProductManageProductId(entry.getKey().toString());
            ecCustomer.setCompanyName(entry.getValue().get(0).getProdName());
            ecCustomer.setWebSite(entry.getValue().get(0).getProdUrl());
            ecCustomer.setType(entry.getValue().get(0).getProdType());
            Set<Long> fbAccountIds = new HashSet<>();
            entry.getValue().forEach(productManageExt -> {
                fbAccountIds.add(productManageExt.getFbAccountId());
            });
            ecCustomer.setFbAccounts(fbAccountIds);
            result.add(ecCustomer);
        }
        return result;
    }

    @Override
    public Collection<EcCustomer> getAllEcCustomerByUserId(String userId) {
        List<UserConnectionPage> pages = adPublishConditionService.findPageIdsByUserId(userId);
        List<ProductManageExt> customersByUserId = productManageRdbService.findEcCustomersByUserId(userId);
        return customersByUserId.stream().map(pm -> {
            EcCustomer ecCustomer = new EcCustomer();
            ecCustomer.setProductManageProductId(pm.getProdId().toString());
            ecCustomer.setCompanyName(pm.getProdName());
            ecCustomer.setWebSite(pm.getProdUrl());
            ecCustomer.setPageId(pages.stream()
                    .filter(p -> pm.getProdId().equals(p.getConnectionObjectId()))
                    .collect(Collectors.toList()).get(0).getPageId().toString());
            return ecCustomer;
        }).collect(toList());
    }

    @Override
    public List<EntrustAccount> findAccountsByProdIdAndUserId(Long prodId, String userId) {
        List<ProductManage> byProductId = productManageRdbService.findByProductId(prodId);
        ProductManage productManage = null;
        if (!byProductId.isEmpty()) {
            productManage = byProductId.get(0);
        }
        if (productManage == null) return new ArrayList<>();
        Long pCfgId = PlatForm.getPlatForm(productManage.getProdPlatform()).getKey().longValue();
        return adPublishConditionService.findAllowedAccounts(userId, productManage.getProdId(), pCfgId);
    }

    @Override
    public List<EcTemplateMateriel> findEcTemplateMaterielByFeedId(Long feedId) {
        // 生成完成 或者之前有生成过
        return ecTemplateMaterielRdbService.findEcTemplateMaterielCanUseCreateAd(feedId);
    }

    @Override
    public Map<String, Object> getFullCondition(Long feedId) {
        //productSet
        JSONObject q = new JSONObject();
        q.put("feed_id", feedId);
        JSONArray productSets = productSetMongoService.getProductSets(q);
        List<JSONObject> prodSets = productSets.stream().map(p -> {
            JSONObject json = (JSONObject) p;
            JSONObject o = new JSONObject();
            o.put("id", json.get("id"));
            o.put("name", json.get("name"));
            return o;
        }).collect(toList());

        //audienceManager
        List<AudienceManager> allByFeed = audienceManagerRdbService.findAllByFeed(feedId);
        List<SimpleVo> ams = allByFeed.stream().map(SimpleVo::new).collect(toList());

        //ecTemplateMateriel
        List<EcTemplateMateriel> templateMateriels = findEcTemplateMaterielByFeedId(feedId);
        List<SimpleVo> tms = templateMateriels.stream().map(SimpleVo::new).collect(toList());

        Map<String, Object> re = new HashMap<>();
        JSONObject placement = new JSONObject();
//        re.put("placement", Arrays.asList(PageType.mobilefeed,PageType.mobileexternal,PageType.desktopfeed,PageType.rightcolumn));
        //这里不能用PageType枚举，因为Facebook发布参数和统计数据名称不统一。暂时写死，最好能根据feed查。
        List<String> placementList = Arrays.asList("mobile_feed", "mobile_external_only", "instagramstream", "desktop_feed", "right_hand");
        placement.put("count", placementList.size());
        placement.put("list", placementList);
        re.put("placement", placement);

        JSONObject productSet = new JSONObject();
        productSet.put("productCount", 0); //// TODO: 2016/5/10   这里取不出来，默认无效值。
        productSet.put("productSetCount", prodSets.size());
        productSet.put("productSetList", prodSets);
        re.put("productSet", productSet);

        JSONObject audienceManager = new JSONObject();
        audienceManager.put("audienceCount", 0);  //// TODO: 2016/5/10   这里取不出来，默认无效值。
        audienceManager.put("audienceGroupCount", ams.size());
        audienceManager.put("audienceGroup", ams);
        re.put("audienceManager", audienceManager);

        JSONObject ecTemplateMateriel = new JSONObject();
        ecTemplateMateriel.put("ecTemplateMaterielCount", tms.size());
        ecTemplateMateriel.put("ecTemplateMateriel", tms);
        re.put("ecTemplateMateriel", ecTemplateMateriel);

        JSONObject billingEvent = new JSONObject();
        billingEvent.put("count", 2);
        billingEvent.put("list", Arrays.asList("LINK_CLICKS", "IMPRESSIONS"));
        re.put("billingEvent", billingEvent);

        JSONObject optimizationGoal = new JSONObject();
        optimizationGoal.put("count", 3);
        optimizationGoal.put("list", Arrays.asList("LINK_CLICKS", "IMPRESSIONS", "OFFSITE_CONVERSIONS"));
        re.put("optimizationGoal", optimizationGoal);

//        JSONObject customEventType=new JSONObject();
//        customEventType.put("count", 2);
//        customEventType.put("list", Arrays.asList("PURCHASE","ADD_TO_CART"));
//        re.put("customEventType", customEventType);

        JSONObject bid = new JSONObject();
        bid.put("count", 2);
        bid.put("list", Arrays.asList("auto", "manual"));
        re.put("bid", bid);
        return re;

    }
}
